package com.syyo.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.syyo.admin.common.enums.ResultEnum;
import com.syyo.admin.common.exception.SysException;
import com.syyo.admin.domain.entity.SysMenu;
import com.syyo.admin.domain.req.MenuReq;
import com.syyo.admin.domain.resp.MenuResp;
import com.syyo.admin.mapper.SysMenuMapper;
import com.syyo.admin.mapper.SysUserMapper;
import com.syyo.admin.service.SysMenuService;
import com.syyo.admin.utils.MyListUtils;
import com.syyo.admin.utils.MyStringUtils;
import com.syyo.admin.utils.SecurityUtils;
import com.syyo.admin.utils.TreeUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wang
 * @since 2020-07-17
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuMapper menuMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Override
    @Transactional
    public int add(MenuReq req) {
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(req,sysMenu);
        List<Integer> pidList = req.getPidList();
        Integer pid = MyStringUtils.getPid(pidList);
        String pids = MyStringUtils.getPids(pidList);
        sysMenu.setPid(pid);
        sysMenu.setPids(pids);
        LocalDateTime now = LocalDateTime.now();
        sysMenu.setCreateTime(now);
        sysMenu.setUpdateTime(now);
        int insert = menuMapper.insert(sysMenu);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80021.getCode(), ResultEnum.E_80021.getMessage());
        }
        return insert;

    }

    @Override
    @Transactional
    public int del(Integer id) {
        int insert = menuMapper.deleteById(id);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80022.getCode(), ResultEnum.E_80022.getMessage());
        }

        // 查询该下面的子级，删除所有子级
        List<Integer> list = menuMapper.findZi(id);
        if (MyListUtils.isNotEmpty(list)) {
            for (Integer integer : list) {
                int i = menuMapper.deleteById(integer);
                if (i != 1) {
                    throw new SysException(ResultEnum.E_80022.getCode(), ResultEnum.E_80022.getMessage());
                }
            }
        }
        return insert;
    }

    @Override
    @Transactional
    public int edit(MenuReq req) {
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(req,sysMenu);
        List<Integer> pidList = req.getPidList();
        Integer pid = MyStringUtils.getPid(pidList);
        String pids = MyStringUtils.getPids(pidList);
        sysMenu.setPid(pid);
        sysMenu.setPids(pids);
        LocalDateTime now = LocalDateTime.now();
        sysMenu.setUpdateTime(now);
        sysMenu.setMenuId(req.getMenuId());
        int insert = menuMapper.updateById(sysMenu);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80023.getCode(), ResultEnum.E_80023.getMessage());
        }
        return insert;
    }

    @Override
    public MenuResp findOne(Integer id) {
        SysMenu sysMenu = menuMapper.selectById(id);
        String pids = sysMenu.getPids();
        List<Integer> list = MyStringUtils.stringToList(pids);
        MenuResp menuResp = new MenuResp();
        BeanUtils.copyProperties(sysMenu,menuResp);
        menuResp.setPidList(list);
        return menuResp;
    }

    @Override
    public List<MenuResp> tree() {
        QueryWrapper<SysMenu> wrapper = new QueryWrapper<SysMenu>();
        wrapper.orderByAsc("sort");
        List<SysMenu> list = menuMapper.selectList(wrapper);
        ArrayList<MenuResp> menuResplist = new ArrayList<>();
        for (SysMenu sysMenu : list) {
            MenuResp menuResp = new MenuResp();
            BeanUtils.copyProperties(sysMenu,menuResp);
            menuResplist.add(menuResp);
        }

        return TreeUtils.listToMenuTree(menuResplist);
    }

    @Override
    public List<Map<String, Object>> buildMenu() {
        //根据token 获取对应的菜单
        String username = SecurityUtils.getUsername();
        List<Integer> roleIds = userMapper.getRoleIdByUserName(username);
        // 菜单去重
        Set<SysMenu> menuSet = new HashSet<>();
        Set<Integer> pisSet = new HashSet<>();
        for (Integer roleId : roleIds) {
            // 添加该用户的所有菜单
            Set<SysMenu> menuResps = menuMapper.getMenuByRoleId(roleId);
            for (SysMenu menuResp : menuResps) {
                String pids = menuResp.getPids();
                String[] split = pids.split(",");
                if (menuResp.getType() == 3) {
                    // 如果是3级，把父级菜单id保存在pisSet里
                    for (String pid : split) {
                        pisSet.add(Integer.parseInt(pid));
                    }
                } else if (menuResp.getType() == 2) {
                    // 如果是2级，把父级菜单id保存在pisSet里，把当前菜单保存在menuSet集合
                    for (String pid : split) {
                        pisSet.add(Integer.parseInt(pid));
                    }
                    menuSet.add(menuResp);
                }
            }
        }

        // 遍历找出改用户的层级菜单
        for (Integer id : pisSet) {
            SysMenu sysMenu = menuMapper.selectById(id);
            menuSet.add(sysMenu);
        }

        //转成list 排序
        List<SysMenu> list = new ArrayList<SysMenu>();
        list.addAll(menuSet);
        Collections.sort(list);

        List<MenuResp> menuResplist = new ArrayList<>();
        for (SysMenu sysMenu : list) {
            MenuResp menuResp = new MenuResp();
            BeanUtils.copyProperties(sysMenu,menuResp);
            menuResplist.add(menuResp);
        }
        List<MenuResp> menuResps = TreeUtils.listToMenuTree(menuResplist);

        return menu_digui(menuResps);
    }

    private List<Map<String, Object>> menu_digui(List<MenuResp> menuResps) {
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        for (MenuResp menuResp : menuResps) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", menuResp.getComponentName());
            map.put("hidden", menuResp.getHidden());
            Map<String, Object> meta = new HashMap<>();
            meta.put("icon", menuResp.getIcon());
            meta.put("title", menuResp.getMenuName());
            meta.put("noCache", menuResp.getCache());
            map.put("meta", meta);
            if (MyStringUtils.isEmpty(menuResp.getComponent())) {
                map.put("path", "/" + menuResp.getPath());
                map.put("component", "Layout");
            } else {
                map.put("path", menuResp.getPath());
                map.put("component", menuResp.getComponent());
            }
            List<MenuResp> children = menuResp.getChildren();
            if (MyListUtils.isNotEmpty(children) && menuResps.size() != maps.size()) {
                List<Map<String, Object>> maps1 = menu_digui(children);
                map.put("children", maps1);
                maps.add(map);
                //递归
            } else if (MyListUtils.isEmpty(children) && menuResps.size() != maps.size()) {
                maps.add(map);
            } else {
                return maps;
            }
        }
        return maps;
    }

    private void createMenu(MenuReq req, SysMenu sysMenu) {
        sysMenu.setMenuName(req.getMenuName());
        List<Integer> pidList = req.getPidList();
        Integer pid = MyStringUtils.getPid(pidList);
        String pids = MyStringUtils.getPids(pidList);
        sysMenu.setPid(pid);
        sysMenu.setPids(pids);
        sysMenu.setPerms(req.getPerms());
        sysMenu.setPath(req.getPath());
        sysMenu.setComponent(req.getComponent());
        sysMenu.setComponentName(req.getComponentName());
        sysMenu.setHidden(req.getHidden());
        sysMenu.setCache(req.getCache());
        sysMenu.setIcon(req.getIcon());
        sysMenu.setType(req.getType());
        sysMenu.setSort(req.getSort());
    }

    private void entityToResp(MenuResp resp, SysMenu sysMenu) {
        resp.setMenuId(sysMenu.getMenuId());
        resp.setMenuName(sysMenu.getMenuName());
        resp.setPid(sysMenu.getPid());
        resp.setPerms(sysMenu.getPerms());
        resp.setPath(sysMenu.getPath());
        resp.setComponent(sysMenu.getComponent());
        resp.setComponentName(sysMenu.getComponentName());
        resp.setHidden(sysMenu.getHidden());
        resp.setCache(sysMenu.getCache());
        resp.setIcon(sysMenu.getIcon());
        resp.setType(sysMenu.getType());
        resp.setSort(sysMenu.getSort());
        resp.setCreateTime(sysMenu.getCreateTime());
        resp.setUpdateTime(sysMenu.getUpdateTime());
        resp.setRemark(sysMenu.getRemark());
    }

}
